package com.zslc.foreignoption.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.zslc.foreignoption.dao.TweetAuthorMapper;
import com.zslc.foreignoption.dao.TweetInfoMapper;
import com.zslc.foreignoption.entity.TweetAuthor;
import com.zslc.foreignoption.entity.TweetInfo;
import com.zslc.foreignoption.service.TweetInfoService;
import com.zslc.foreignoption.util.HttpUtilTest;
import com.zslc.foreignoption.util.ResultCMS;
import com.zslc.foreignoption.util.ShUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @version 1.0
 * @description:
 * @author: Gaoyc
 * @date: 2024-06-21 16:38
 **/
@Slf4j
@Service
public class TweetInfoServiceImpl implements TweetInfoService {
    @Resource
    private TweetInfoMapper tweetInfoMapper;
    @Resource
    private TweetAuthorMapper tweetAuthorMapper;
    @Value("${file.author.picturePath}")
    private String authorPicRootPath;
    @Value("${file.forum.videoPath}")
    private String videoRootPath;
    @Value("${file.forum.picturePath}")
    private String pictureRootPath;
    @Value("${openai.api_key}")
    private String openaiApiKey;
    @Value("${openai.translate_api}")
    private String translateUrl;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer insertTweetData(JSONObject tweetDataMap,String accountId) {
        String ahtuorUuid = "-1";
        String ahtuorId = "-1";
        JSONObject authorMap = tweetDataMap.getJSONObject("author");
        if (authorMap == null) {
            log.error("【author】为空值，tweetData全文：{}", JSONObject.toJSONString(tweetDataMap));
        } else {
            if(StringUtils.isNotEmpty(accountId)) {
                ahtuorId = authorMap.getString("id");
                ahtuorUuid = saveAuthor(authorMap, accountId);
            }
            String tweetId = tweetDataMap.getString("id");
            String userName = authorMap.getString("userName");
            String profilePicture = authorMap.getString("profilePicture");
            String name = authorMap.getString("name");
            String description = authorMap.getString("description");
            Map<String, String> inAuthorMap = new HashMap<>();
            inAuthorMap.put("tweetId", tweetId);
            inAuthorMap.put("userName", userName);
            inAuthorMap.put("profilePicture", profilePicture);
            inAuthorMap.put("name", name);
            inAuthorMap.put("description", description);
            //
            tweetDataMap.put("inAuthorMap", JSONObject.toJSONString(inAuthorMap));
        }


        String postId = tweetDataMap.getString("id");
        JSONObject extendedEntities = tweetDataMap.getJSONObject("extendedEntities");
        JSONObject card = tweetDataMap.getJSONObject("card");
        JSONObject place = tweetDataMap.getJSONObject("place");
        JSONObject entities = tweetDataMap.getJSONObject("entities");
        JSONArray media = tweetDataMap.getJSONArray("media");
        tweetDataMap.put("card",JSONObject.toJSONString(card));
        tweetDataMap.put("place",JSONObject.toJSONString(place));
        tweetDataMap.put("media",JSONObject.toJSONString(media));
        tweetDataMap.put("extendedEntities",JSONObject.toJSONString(extendedEntities));

        //下载视频
        if(CollectionUtil.isNotEmpty(media)){
            JSONArray media1 = entities.getJSONArray("media");
            for (Object o : media1) {
                JSONObject jsonObject = (JSONObject) o;
                String type = jsonObject.getString("type");
                if(StringUtils.equals("photo",type)){
                    String mediaUrlHttps = jsonObject.getString("media_url_https");
                    String localMediaUrlHttps = saveVideoPic(mediaUrlHttps, ahtuorId, postId);
                    jsonObject.put("media_url_https",localMediaUrlHttps);
                }else if(StringUtils.equals("video",type)){
                    String mediaUrlHttps = jsonObject.getString("media_url_https");
                    String localMediaUrlHttps = saveVideoPic(mediaUrlHttps, ahtuorId, postId);
                    jsonObject.put("media_url_https",localMediaUrlHttps);

                    JSONObject video_info = jsonObject.getJSONObject("video_info");
                    JSONArray variants = video_info.getJSONArray("variants");
                    for (Object object : variants) {
                        JSONObject variant= (JSONObject)object;
                        String type1 = variant.getString("content_type");
                        if(StringUtils.equals("application/x-mpegURL",type1)){
                            String videoUrl = variant.getString("url");
                            String saveForumVideo = saveForumVideo(videoUrl, ahtuorId, postId);
                            variant.put("url", saveForumVideo);
                        }
                    }
                }
            }
        }
        tweetDataMap.put("entities",JSONObject.toJSONString(entities));

        Integer num = 0;
        String id = tweetDataMap.getString("id");
        TweetInfo info = tweetInfoMapper.selectOneById(id);
        if (info == null) {
            //翻译文本
            String text = tweetDataMap.getString("text");
            if (StringUtils.isNotEmpty(text)) {
                Map<Integer, String> integerStringMap = transferText(text);
                String textZh = integerStringMap.get(0);
                tweetDataMap.put("text_zh", textZh);
            }

            tweetDataMap.put("authorId",ahtuorUuid);
            tweetDataMap.put("uuid", UUID.randomUUID().toString());
            num = tweetInfoMapper.insertTweetData(tweetDataMap);
        }
        return num;
    }

    @Override
    public List<TweetInfo> list(Integer page, Integer pageSize) {
        List<TweetInfo> list = tweetInfoMapper.list(page,pageSize);
        return list;
    }

    @Override
    public Integer count() {
        return tweetInfoMapper.count();
    }
    public String saveAuthor(JSONObject authorMap,String accountId){
        String ahtuorUuid = UUID.randomUUID().toString();
        try {
            String authorId = authorMap.getString("id");
            TweetAuthor tweetAuthor = tweetAuthorMapper.selectOneById(authorId);
            if (tweetAuthor == null) {
                authorMap.put("parent_id", accountId);
                authorMap.put("uuid", ahtuorUuid);
                //获取expanded_url字段值
                JSONObject entitiesObject = authorMap.getJSONObject("entities");
                JSONObject urlObject = entitiesObject.getJSONObject("url");
                if (urlObject != null) {
                    JSONArray urlsArray = urlObject.getJSONArray("urls");
                    StringBuilder sb = new StringBuilder();
                    for (Object url : urlsArray) {
                        JSONObject url1 = (JSONObject) url;
                        String expandedUrl = url1.getString("expanded_url");
                        sb.append(expandedUrl).append(",");
                    }
                    String expanded_url = sb.substring(0, sb.lastIndexOf(",")).toString();
                    authorMap.put("expanded_url", expanded_url);
                }
                //下载图片
                String id = authorMap.getString("id");
                String profilePicture = authorMap.getString("profilePicture");
                String localProfilePicture = saveAuthorPic(profilePicture, id);
                authorMap.put("profilePicture", localProfilePicture);

                String coverPicture = authorMap.getString("coverPicture");
                String localCoverPicture = saveAuthorPic(coverPicture, id);
                authorMap.put("coverPicture", localCoverPicture);

                Integer num1 = tweetAuthorMapper.insertTweetAuthor(authorMap);
            } else {
                ahtuorUuid = tweetAuthor.getUuid();
            }
        } catch (Exception e) {
            log.error("保存Ahthor信息出错",e);
        }
        return ahtuorUuid;
    }

    private String saveAuthorPic(String picPath, String authorId){
        if (StringUtils.isEmpty(picPath)) {
            log.warn("authorId=【{}】推特作者图片地址为空",authorId);
            return "";
        }
//        String commond = "yt-dlp --proxy http://127.0.0.1:8890 https://pbs.twimg.com/ext_tw_video_thumb/1803456946370174976/pu/img/N_aOiolf3F8S-ukQ.jpg -o 111.jpg";
        String saveRootPath = authorPicRootPath;
        String picName = StringUtils.substring(picPath, picPath.lastIndexOf("/")+1);
        if(!StringUtils.endsWith(picName,".jpg")){
            picName = picName + ".jpg";
        }
        // 获取当前日期
        Date now = new Date();
        // 创建日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("/yyyy/MM/dd");
        // 生成日期路径
        String datePath = dateFormat.format(now);
        StringBuilder savePath = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId);
        File directory = new File(savePath.toString());
        // 判断路径是否存在
        if (!directory.exists()) {
            // 如果不存在，则创建目录
            directory.mkdirs();
        }
        savePath.append("/"+picName);
        File file = new File(savePath.toString());
        if (!file.exists()) {
            StringBuilder sb = new StringBuilder();
            sb.append("source /data/wwwroot/foreign-option/conda.sh;");
            sb.append(" yt-dlp --proxy http://127.0.0.1:8890 ");
            sb.append(picPath);
            sb.append(" -o ");
            sb.append(savePath);
            log.info("下载作者图片命令：【{}】",sb.toString());
            boolean flag = ShUtil.shHandel0(sb.toString());
            log.info("下载作者图片【{}】，返回结果【{}】",sb.toString(),flag);
            if (flag) {
                return savePath.toString();
            }else{
                return picPath;
            }
        }
        return savePath.toString();
    }
    private String saveVideoPic(String picPath, String authorId,String postId){
//        String commond = "yt-dlp --proxy http://127.0.0.1:8890 https://pbs.twimg.com/ext_tw_video_thumb/1803456946370174976/pu/img/N_aOiolf3F8S-ukQ.jpg -o 111.jpg";
        String saveRootPath = pictureRootPath;
        String picName = StringUtils.substring(picPath, picPath.lastIndexOf("/")+1);
        if(!StringUtils.endsWith(picName,".jpg")){
            picName = picName + ".jpg";
        }
        // 获取当前日期
        Date now = new Date();
        // 创建日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("/yyyy/MM/dd");
        // 生成日期路径
        String datePath = dateFormat.format(now);
        StringBuilder savePath = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId);
        File directory = new File(savePath.toString());
        // 判断路径是否存在
        if (!directory.exists()) {
            // 如果不存在，则创建目录
            directory.mkdirs();
        }
        savePath.append("/"+picName);

        File file = new File(savePath.toString());
        if (!file.exists()) {
            StringBuilder sb = new StringBuilder();
            sb.append("source /data/wwwroot/foreign-option/conda.sh;");
            sb.append(" yt-dlp --proxy http://127.0.0.1:8890 ");
            sb.append(picPath);
            sb.append(" -o ");
            sb.append(savePath);
            log.info("下载视频图片命令：【{}】",sb.toString());
//        Integer i = ProcessUtils.execCommandNeedWaitForWithReturn(sb.toString());
            boolean flag = ShUtil.shHandel0(sb.toString());
            log.info("下载视频图片【{}】，返回结果【{}】",sb.toString(),flag);
            if (true) {
                return savePath.toString();
            }else{
                return picPath;
            }
        }
        return savePath.toString();
    }

    private String saveForumVideo(String videoPath, String authorId, String postId){
        //下载音频：//取"content_type": "application/x-mpegURL"的视频地址
//        String commond = "yt-dlp --proxy http://127.0.0.1:8890 -f bv+ba https://video.twimg.com/amplify_video/1803771519149195264/pl/F9IKKnJ2aRwIlEjz.m3u8 -o video.mp4";
//        yt-dlp --proxy http://127.0.0.1:8890 -f ba https://video.twimg.com/amplify_video/1803771519149195264/pl/F9IKKnJ2aRwIlEjz.m3u8 -o audio.mp4
        String saveRootPath = videoRootPath;
        String videoFullName = StringUtils.substring(videoPath, videoPath.lastIndexOf("/")+1);
        String videoName = StringUtils.substring(videoFullName, 0, videoFullName.indexOf("."));

        // 生成日期文件夹
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("/yyyy/MM/dd");
        String datePath = dateFormat.format(now);
        StringBuilder savePath = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId);
        File directory = new File(savePath.toString());
        // 判断路径是否存在
        if (!directory.exists()) {
            directory.mkdirs();
        }
        savePath.append("/"+videoName).append(".mp4");

        File file = new File(savePath.toString());
        if (!file.exists()) {
            boolean flag = saveM3u8Video(videoPath, savePath.toString());
            if (flag) {
                //转码MP4文件为m3u8
                StringBuilder savem3u8Path = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId).append("/"+videoName).append(".m3u8");
                File savem3u8File = new File(savem3u8Path.toString());
                if (!savem3u8File.exists()) {
                    transferM3u8Video(savePath.toString(), savem3u8Path.toString());
                }
                //下载音频
                StringBuilder saveAudioPath = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId).append("/"+videoName).append("_audio").append(".mp4");
                File saveAudioFile = new File(saveAudioPath.toString());
                if (!saveAudioFile.exists()) {
                    saveAudio(saveAudioPath.toString(),videoPath);
                }
                return savem3u8Path.toString();
            }
        }else{
            StringBuilder savem3u8Path = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId).append("/"+videoName).append(".m3u8");
            File savem3u8File = new File(savem3u8Path.toString());
            if (!savem3u8File.exists()) {
                transferM3u8Video(savePath.toString(), savem3u8Path.toString());
            }

            StringBuilder saveAudioPath = new StringBuilder().append(saveRootPath).append(datePath).append("/"+authorId).append("/"+postId).append("/"+videoName).append("_audio").append(".mp4");
            File saveAudioFile = new File(saveAudioPath.toString());
            if (!saveAudioFile.exists()) {
                saveAudio(saveAudioPath.toString(),videoPath);
            }
            return savem3u8Path.toString();
        }
        return videoPath;
    }

    private boolean transferM3u8Video(String savePath,String savem3u8Path){
        String menu = StringUtils.substring(savePath, 0, savePath.lastIndexOf("/"));

        // 判断路径是否存在
        String dir = menu+"/ts";
        File directory = new File(dir);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        StringBuilder sb0 = new StringBuilder();
        sb0.append("source /data/wwwroot/foreign-option/conda.sh;");
        sb0.append(" /usr/local/ffmpeg/bin/ffmpeg -i ");
        sb0.append(savePath);
        sb0.append(" -codec: copy -start_number 0 -f hls -hls_time 3  -hls_list_size 0 -hls_segment_filename ");
        sb0.append(menu+"/ts/%06d.ts");
        sb0.append(" -hls_base_url ");
        sb0.append(menu+"/ts ");
        sb0.append(savem3u8Path);
        sb0.append(" -y");
        log.info("转码MP4视频成m3u8视频命令：【{}】",sb0.toString());
        boolean b = ShUtil.shHandel0(sb0.toString());
        log.info("转码MP4视频成m3u8视频【{}】，返回结果【{}】",sb0.toString(),b);
        return b;
    }

    private boolean saveM3u8Video(String videoPath,String savePath){
        StringBuilder sb = new StringBuilder();
        sb.append("source /data/wwwroot/foreign-option/conda.sh;");
        sb.append(" yt-dlp --proxy http://127.0.0.1:8890 ");
        sb.append(" -f bv+ba ");
        sb.append(videoPath);
        sb.append(" -o ");
        sb.append(savePath);
        log.info("下载m3u8视频命令：【{}】",sb.toString());
        boolean flag = ShUtil.shHandel0(sb.toString());
        log.info("下载m3u8视频【{}】，返回结果【{}】",sb.toString(),flag);
        return flag;
    }

    @Async
    public void saveAudio(String saveAudioPath, String videoPath){
        StringBuilder sb1 = new StringBuilder();
        sb1.append("source /data/wwwroot/foreign-option/conda.sh;");
        sb1.append(" yt-dlp --proxy http://127.0.0.1:8890 ");
        sb1.append(" -f ba ");
        sb1.append(videoPath);
        sb1.append(" -o ");
        sb1.append(saveAudioPath);
        log.info("下载音频命令：【{}】",sb1.toString());
        boolean b = ShUtil.shHandel0(sb1.toString());
        log.info("下载音频【{}】，返回结果【{}】",sb1.toString(),b);
    }


    private Map<Integer, String> transferText(String text){
        String url = translateUrl;
        Map<Integer, String> map = new HashMap<>();
        //去除换行符
        text = text.replaceAll("\\r?\\n", " ");
        //针对包含链接的内容转义
        text = URLUtil.encode(text);
        log.info("openai翻译接口开始调用，请求文本：【{}】",text);
        ResultCMS resultCMS = HttpUtilTest.sendPostRequest(url, openaiApiKey, text);
        log.info("openai翻译接口调用结束，返回结果：【{}】",resultCMS);
        if (StringUtils.equals("200", resultCMS.getSuccess())) {
            String data = (String) resultCMS.getData();
            JSONObject jsonObject = JSONObject.parseObject(data);
            JSONArray choices = jsonObject.getJSONArray("choices");
            for (Object choice : choices) {
                JSONObject json = (JSONObject) choice;
                Integer index = json.getInteger("index");
                JSONObject message = json.getJSONObject("message");
                String content = message.getString("content");
               /* if (StringUtils.startsWith(content, "**翻译：**")) {
                    content = StringUtils.removeStart(content, "**翻译：**");
                }*/
                map.put(index, content);
            }
        }
        return map;
    }

}
